package com.you.nettty.rpc.registry;

import com.you.nettty.rpc.constant.RpcRegistryConstants;
import com.you.nettty.rpc.protocol.InvokerProtocol;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter;

import java.io.File;
import java.lang.reflect.Method;
import java.net.URL;

/**
 * Rpc Registry注册中心处理类
 */
public class RpcRegistryHandler extends ChannelInboundHandlerAdapter {

    public RpcRegistryHandler() throws Exception {
        //扫描指定包路径下的class实现类，把包路径+类名存放到RpcRegistryConstants.classNames列表中
        scannerClass("com.you.provider.service.impl");
        //完成所有实现类服务的注册
        doRegister();
    }

    /**
     * 完成服务的注册
     *
     * @throws Exception
     */
    private void doRegister() throws Exception {
        if (RpcRegistryConstants.classNames.size() == 0) {
            return;
        }
        for (String className : RpcRegistryConstants.classNames) {
            try {
                Class<?> clazz = Class.forName(className);
                Class<?> inter = clazz.getInterfaces()[0];
                RpcRegistryConstants.serviceRegistryMap.put(inter.getName(), clazz.newInstance());
            } catch (Exception ex) {
                ex.printStackTrace();
                throw ex;
            }
        }
    }

    /**
     * 递归扫描指定包路径下的class实现类，把包路径+类名存放到RpcRegistryConstants.classNames列表中
     *
     * @param packageName
     */
    private void scannerClass(String packageName) {
        URL url = this.getClass().getClassLoader().getResource(packageName.replaceAll("\\.", "/"));
        File dir = new File(url.getFile());
        for (File file : dir.listFiles()) {
            if (file.isDirectory()) {
                scannerClass(packageName + "." + file.getName());
            } else {
                RpcRegistryConstants.classNames.add(packageName + "." + file.getName().replace(".class", "").trim());
            }
        }
    }

    /**
     * 接收客户端的调用请求
     *
     * @param ctx
     * @param msg
     * @throws Exception
     */
    @Override
    public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
        Object result = new Object();
        System.out.println("------get client request msg is : " + msg);
        InvokerProtocol request = (InvokerProtocol) msg;
        //当客户端建立连接时，需要从自定义协议中获取信息，拿到具体的服务和形参
        //使用反射调用
        if (RpcRegistryConstants.serviceRegistryMap.containsKey(request.getClassName())) {
            //通过接口名称找到对应的实现类对象
            Object realObj = RpcRegistryConstants.serviceRegistryMap.get(request.getClassName());
            //根据给定的参数类型列表，找到对应的实现方法
            Method method = realObj.getClass().getMethod(request.getMethodName(), request.getParames());
            //通过反射机制调用实现类的方法
            result = method.invoke(realObj, request.getValues());
        }
        ctx.write(result);
        ctx.flush();
        ctx.close();
    }

    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
        super.exceptionCaught(ctx, cause);
        ctx.close();
    }
}
